/**
 * 
 */
package cn.edu.bjtu.alex.rewrite.components;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import com.google.common.collect.Maps;

import cn.edu.bjtu.alex.rewrite.Context;
import cn.edu.bjtu.alex.rewrite.interfaces.TermFeatureable;
import cn.edu.bjtu.alex.rewrite.tools.FileUtils;
import cn.edu.bjtu.alex.rewrite.tools.MetricUtils;

/**
 * 这一个类主要是用来输出三个文件,label.txt feature.txt 和vectors.txt<br>
 * label是类标映射,featrue.txt就是词典 ,vecots就是变成向量之后文档<br>
 * vectors可以用来建立分类器<br>
 * 词典在将测试集转换成向量的过程中用得到<br>
 * @author alex
 *
 */
public class TrainOutputing extends BaseOutputingData{

	private int labelNumber = 0;
	private int wordNumber = 0;
	public TrainOutputing(Context ctx) {
		super(ctx);
	}
	@Override
	protected void quantizeTermVectors() {
		// store all <label, labelId> pairs
		Map<String, Integer> globalLabelToIdMap = Maps.newHashMap();
		// store all <labelId, label> pairs
		Map<Integer, String> globalIdToLabelMap = Maps.newHashMap();
		
		// generate label id
		for(String label : ctx.labels()) {
			Integer labelId = globalLabelToIdMap.get(label);
			if(labelId == null) {
				++labelNumber;
				labelId = labelNumber;
				globalLabelToIdMap.put(label, labelId);
				globalIdToLabelMap.put(labelId, label);
			}
		}
		
		// generate word id from featured term collection
		for(TermFeatureable term : ctx.featuredTerms()) {
			term.setId(++wordNumber);
		}
		
		// store meta data
		ctx.putLabelToIdPairs(globalLabelToIdMap);
		ctx.putIdToLabelPairs(globalIdToLabelMap);
		
		quantizeLabelMappingAndDicitionary();
	}
	private void outputFeatureTermVector() {
		BufferedWriter w = null;
		try {
			// ctx.termTableIterator()
			File f = new File(ctx.getOutputDir(),ctx.getFeatureTermVectorFileName());
			w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), ctx.getCharset()));
			int totalDocCount = ctx.totalDocCount();
			for(TermFeatureable term : ctx.featuredTerms()) {
				String word = term.getWord();
				Integer wordId = term.getId();
				//计算idf值
				int docCountContainingTerm=0;
				Map<String, Set<String>> labelledDocs = ctx.getInvertedTable().get(word);
				Iterator<Entry<String, Set<String>>> iter = labelledDocs.entrySet().iterator();
				while(iter.hasNext()) {
					docCountContainingTerm += iter.next().getValue().size();
				}
				double idf=MetricUtils.idf(totalDocCount, docCountContainingTerm);
				StringBuffer buf = new StringBuffer();
				buf.append(word).append("\t").append(wordId).append("\t").append(idf);
				//同时更新featureTerms中的meausreValue 这个值修改之前是卡方选择计算出来的特征值
				//转换文档的时候是用这个值去乘词的tf值
				ctx.featuredTermsMap().get(word).setMeasureValue(idf);
				
				LOG.debug("Write feature term vector: word=" + word + ", datum=" + buf.toString());
				w.write(buf.toString());
				w.newLine();
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			FileUtils.closeQuietly(w);
		}
	}

	private void output(File file, Iterator<Entry<String, Integer>> iter) {
		BufferedWriter w = null;
		try {
			w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), ctx.getCharset()));
			while(iter.hasNext()) {
				Entry<String, Integer> entry = iter.next();
				w.write(entry.getValue().toString() + " " + entry.getKey());
				w.newLine();
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			FileUtils.closeQuietly(w);
		}
	}

	protected void quantizeLabelMappingAndDicitionary() {
		outputFeatureTermVector();
		output(new File(ctx.getOutputDir(),ctx.getLabelVectorFileName()), ctx.labelVectorMapIterator());
	}
	/* (non-Javadoc)
	 * @see cn.edu.bjtu.alex.rewrite.components.BaseComponent#transformInternal()
	 */
	@Override
	protected void transformInternal() {
		// TODO Auto-generated method stub
		
	}
}
